/*
 * File    : /encode.js
 * Time    : 2021-04-25 22:18:17
 * Author  : Gray Snail
 * Version : 1.0
 * Contact : shtao2011@sina.com
 * License : Copyright (c) 2021 Gray Snail
 * Desc    : None
 */

// begin: 压缩算法
function encodePolygon(coordinate, encodeOffsets) {
  var result = '';
  var prevX = quantize(coordinate[0][0]);
  var prevY = quantize(coordinate[0][1]);
  // Store the origin offset
  encodeOffsets[0] = prevX;
  encodeOffsets[1] = prevY;
  for (var i = 0; i < coordinate.length; i++) {
    var point = coordinate[i];
    result += encode(point[0], prevX);
    result += encode(point[1], prevY);
    prevX = quantize(point[0]);
    prevY = quantize(point[1]);
  }
  return result;
}

function encode(val, prev) {
  // Quantization
  val = quantize(val);

  val = val - prev;
  if (((val << 1) ^ (val >> 15)) + 64 === 8232) {
    //WTF, 8232 will get syntax error in js code
    val--;
  }
  // ZigZag
  val = (val << 1) ^ (val >> 15);
  // add offset and get unicode
  return String.fromCharCode(val + 64);
}
function quantize(val) {
  return Math.ceil(val * 1024);
}

function encodeGeo(geo) {
  // 压缩标识
  geo.UTF8Encoding = true;
  geo.UTF8Scale = 1024;

  for (let f_i = 0; f_i < geo.features.length; f_i++) {
    var geometry = geo.features[f_i].geometry;
    if (geometry.type === 'Polygon') {
      var coordinates = geometry.coordinates;
      geometry.encodeOffsets = Array(coordinates.length);
      for (let c = 0; c < coordinates.length; c++) {
        var offset = Array(2);
        var codeStr = encodePolygon(coordinates[c], offset);
        coordinates[c] = codeStr;
        geometry.encodeOffsets[c] = offset;
      }
    } else if (geometry.type === 'MultiPolygon') {
      var coordinates = geometry.coordinates;
      geometry.encodeOffsets = Array(coordinates.length);
      for (let c = 0; c < coordinates.length; c++) {
        var coordinate = coordinates[c];
        geometry.encodeOffsets[c] = Array(coordinate.length);

        for (let c2 = 0; c2 < coordinate.length; c2++) {
          var offset = Array(2);
          var codeStr = encodePolygon(coordinate[c2], offset);
          coordinate[c2] = codeStr;
          geometry.encodeOffsets[c][c2] = offset;
        }
      }
    }
  }
  return geo;
}

function addAMDWrapper(jsonStr) {
  return ['define(function() {', '    return ' + jsonStr + ';', '});'].join('\n');
}

function addEchartsJsWrapper(jsonStr, fileName) {
  return [
    '(function (root, factory) {',
    "   if (typeof define === 'function' && define.amd) {",
    "       define(['exports', 'echarts'], factory);",
    "   } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {",
    "       factory(exports, require('echarts'));",
    '   } else {',
    '       factory({}, root.echarts);',
    '   }',
    ' }(this, function (exports, echarts) {',
    '       var log = function (msg) {',
    "           if (typeof console !== 'undefined') {",
    '               console && console.error && console.error(msg);',
    '           }',
    '       }',
    ' if (!echarts) {',
    "       log('ECharts is not Loaded');",
    '           return;',
    '       }',
    ' if (!echarts.registerMap) {',
    "       log('ECharts Map is not loaded')",
    '       return;',
    ' }',
    "  echarts.registerMap('" + fileName + "'," + jsonStr,
    '  )}));',
  ].join('\n');
}

function convert2Echarts(rawStr, fileName, type) {
  var json = encodeGeo(JSON.parse(rawStr));
  if (type === 'json') {
    results = JSON.stringify(json);
  } else {
    results = addEchartsJsWrapper(JSON.stringify(json), fileName);
  }
  return results;
}
